using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Client.Protocol;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Client
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
        }

        DistributiedFilesSystemMaster filesSystemMaster = new DistributiedFilesSystemMaster();
        private delegate void displayDlg(string list);
        private delegate void updateInterfaceDlg(Command cmd);

        //client wait the message from server and procees them

       

        #region interpret command from command line
        string fixComand(string cmd)
        {
            string returnCMD;
            String[] tokenns = cmd.Split(new char[] { ' ' });
            if (tokenns.Length >1)
            {
                if (tokenns[0].ToLower() == "cd")
                {
                    if (!tokenns[1].ToLower().StartsWith("root\\") && this.txtCurrentDir.Text.Length > 5)
                    {
                        returnCMD = "cd ";
                        returnCMD += this.txtCurrentDir.Text.Substring(5);
                        if (tokenns[1] != "..")
                        {
                            returnCMD += "\\";
                            returnCMD += tokenns[1];
                        }
                        else
                        {
                            int splitLocation = returnCMD.LastIndexOf('\\');
                            if (splitLocation > -1)
                            {
                                returnCMD = returnCMD.Substring(0, returnCMD.LastIndexOf('\\'));
                            }
                            else
                            {
                                returnCMD = "";
                                this.txtCurrentDir.Text = "root\\";
                            }
                        }
                    }
                    else
                    {
                        returnCMD = cmd;
                    }
                }
                else if (tokenns[0].ToLower() == "ls")
                {
                    if (!tokenns[1].ToLower().StartsWith("root\\") && this.txtCurrentDir.Text.Length > 5)
                    {
                        returnCMD = "ls ";
                        returnCMD += this.txtCurrentDir.Text.Substring(5);
                        returnCMD += "\\";
                        returnCMD += tokenns[1];
                    }
                    else
                    {
                        returnCMD = cmd;
                    }
                
                }
                else
                {
                    returnCMD = cmd;
                }
            }
            else 
            {
                if (tokenns[0].ToLower() == "ls")
                {
                    returnCMD = "ls ";
                    returnCMD += this.txtCurrentDir.Text.Substring(5);
                }
                else
                {
                    returnCMD = cmd;
                }
            }
            return returnCMD;

        }
        private void txtCommand_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                int endOfRoot = this.txtCurrentDir.Text.IndexOf('\\');//end of root
                string path = this.txtCurrentDir.Text.Substring(endOfRoot+1);
                string finalCommand = fixComand(this.txtCommand.Text);
                string[] tempVars = finalCommand.Split(' ');
                if ( (tempVars.Length > 1) && (tempVars[0] != "ls") && (tempVars[0] != "cd" ))
                {
                    string tempCmd = tempVars[0] + " " + ( (path == "") ? "" : (path + "\\") ) + tempVars[1];
                    finalCommand = tempCmd;
                }
                
                //Command responseCmd = filesSystemMaster.executStringCommand(fixComand(this.txtCommand.Text));
                Command responseCmd = filesSystemMaster.executStringCommand(finalCommand);
                execCommand(responseCmd);
                this.txtCommand.Text = "";
                this.txtCommand.Refresh();
            }
        }



        private void displayMessage(string message)
        {
            displayDlg myDelegate = new displayDlg(addMesage);
            txtLog.Invoke(myDelegate, message);
        }

        private void displayNewServersList(Command cmd)
        {
            switch (cmd.ID)
            {
                case (int)Constants.cmd.CMD_GET_SERVERS_ADRESSES:
                    {
                        updateInterfaceDlg myDelegate = new updateInterfaceDlg(changeServersList);
                        ServerActivList.Invoke(myDelegate, cmd);
                    }
                    break;
                case (int)Constants.cmd.CMD_LIST_DIR:
                    {
                        updateInterfaceDlg myDelegate = new updateInterfaceDlg(changeFileList);
                        ServerActivList.Invoke(myDelegate, cmd);
                    }
                    break;
            }
        }

        private void changeServersList(Command listServers)
        { 
            for (int i =0 ; i< listServers.Params.Count;i++)
            {
                      
                      chLstBxServers.Items.Add(listServers.Params[i].Val);
            }
        
        }

        private void changeFileList(Command filelist)
        {
            listView.Items.Clear();
            //find the node tree for update
            //test only the first param path
            string path;
            string name;
            int splitLocation;
            TreeNode updateNode= new TreeNode();
            if (filelist.Params.Count > 0)
            {
                path = filelist.Params[0].Val;
                splitLocation = path.LastIndexOf('\\');
                if (splitLocation > -1)
                {
                    /*name = path.Substring(split + 1);0*/
                    path = path.Substring(0, splitLocation);
                    updateNode = TreeView.Nodes[0];
                    string[] dirs = path.Split(new char[] { '\\' });
                    int it = 0;
                    for (it = 0; it < dirs.Length;it++ )
                    {
                        bool existNode = false;
                        int itTree;
                        for (itTree = 0; itTree < updateNode.Nodes.Count; itTree++)
                        {
                            if (updateNode.Nodes[itTree].Text == dirs[it])
                            {
                               existNode= true ;
                               break;
                            }
                        }
                        if ( existNode == false)
                            {
                                TreeNode newNode = new TreeNode(dirs[it]);
                                updateNode.Nodes.Add(newNode);
                                updateNode = newNode;

                            }
                            else
                            {
                                updateNode = updateNode.Nodes[itTree];
                            }
                       
                    }
                    updateNode.Nodes.Clear();
                }
                else
                {
                    name = path;
                    path = "root";
                    updateNode = TreeView.Nodes[0];
                    updateNode.Nodes.Clear();
                }

            }
            updateNode.Nodes.Clear();

            //end the node tree for update
            for (int i = 0; i < filelist.Params.Count; i++)
            {
                name = filelist.Params[i].Val;
                splitLocation = name.LastIndexOf('\\');
                if (splitLocation > -1)
                {
                    name = name.Substring(splitLocation + 1);
                  //  path = path.Substring(0, split);
                }
                ListViewItem itm = new ListViewItem(name);
                
                i++;
                if (filelist.Params[i].Val == "folder")
                {
                    itm.ImageIndex = 1;
                    TreeNode newnode = new TreeNode(name);
                    updateNode.Nodes.Add(newnode);

                  //  if (path == name)
                    //{
                      //  TreeView.Nodes[0].Nodes.Add(name);
                    //}
                    //else
                    //{ 
                    //}
                }
                else
                { 
                    itm.ImageIndex = 0; 
                }
                    listView.Items.Add(itm);
               
            }

        }

        private void changeCurrentDir(Command currentDir)
        {
            if (!bool.Parse(currentDir.Params[0].Val))
            {
                System.Windows.Forms.MessageBox.Show("Path " + currentDir.Params[1].Val + " does not exist!!!");
            }
            else 
            {
                this.txtCurrentDir.Text ="root\\";
                this.txtCurrentDir.Text += currentDir.Params[1].Val;
                this.txtCurrentDir.Refresh();
            }

        }

        private void addMesage(string message)
        {
            this.txtLog.Text += "\r\n";
            this.txtLog.Text += message;
            this.txtLog.Invalidate();
        }

        //proces the command recived from servers
        private void execCommand(Command cmd)
        {
            switch (cmd.ID)
            {
                case (int)Constants.cmd.CMD_GET_SERVERS_ADRESSES:
                    {
                        displayMessage("Ip list Recieved");
                        for (int i = 0; i < cmd.Params.Count; ++i)
                        {
                            displayMessage(cmd.Params[i].Val);
                        }
                        displayNewServersList(cmd);
                    }
                    break;
                case (int)Constants.cmd.CMD_LIST_DIR:
                    {
                        changeFileList(cmd);
                    }
                    break;
                case (int)Constants.cmd.CMD_CHANGE_DIR:
                    {
                        changeCurrentDir(cmd);
                    }
                    break;
                case (int)Constants.cmd.CMD_NEW_FILE:
                    {
                        for (int i = 0; i < cmd.Params.Count; ++i)
                        {
                            if (cmd.Params[i].Name.CompareTo(Constants.STATUS_PARAM) == 0)
                            {
                                displayMessage("CMD_NEW_FILE Status : " + cmd.Params[i].Val);
                                break;
                            }
                        }
                    }
                    break;
                case (int)Constants.cmd.CMD_MAKE_DIR:
                    {
                        for (int i = 0; i < cmd.Params.Count; ++i)
                        {
                            if (cmd.Params[i].Name.CompareTo(Constants.STATUS_PARAM) == 0)
                            {
                                displayMessage("CMD_MAKE_DIR Status : " + cmd.Params[i].Val);
                                break;
                            }
                        }
                    }
                    break;
                default:
                    {
                        //displayMessage("Wrong command or parameters :) or function not implemented");
                    } 
                    break;

            }
        }

        private int getCmdId(string token)
        {
            int cmdType = (int)Constants.cmd.CMD_LIST_END;
            if (token == "cd")
            {
                cmdType = (int)Constants.cmd.CMD_CHANGE_DIR;
            }

            else if (token == "ls")
            {
                cmdType = (int)Constants.cmd.CMD_LIST_DIR;
            }

            else if (token == "mkdir")
            {
                cmdType = (int)Constants.cmd.CMD_MAKE_DIR;
            }

            else if (token == "md")
            {
                cmdType = (int)Constants.cmd.CMD_CHANGE_DIR;
            }

            else if (token == "nf")
            {
                cmdType = (int)Constants.cmd.CMD_NEW_FILE;
            }

            else if (token == "sw")
            {
                cmdType = (int)Constants.cmd.CMD_SHOW_FILE;
            }

            if (token == "exit")
            {
                cmdType = (int)Constants.cmd.CMD_EXIT;
            }
            return cmdType;
        }
        #endregion

       
        private void btnGetServConfig_Click(object sender, EventArgs e)
        {
            if (txtIP.Text == "" || txtPort.Text == "")
            {
                MessageBox.Show("IP Address and Port Number are required to connect to the Server\n");
                return;
            }
            Command  responseCmd =  filesSystemMaster.executStringCommand("getSLst " + txtIP.Text + " " + txtPort.Text + " ");
            execCommand(responseCmd);
       }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
        }

        private void btnDisconect_Click(object sender, EventArgs e)
        {
            if (chLstBxServers.Items.Count > 0)
            {
                string cmd = "disconnectS ";
                for (int i = 0; i < chLstBxServers.Items.Count; i++)
                {
                    cmd += chLstBxServers.Items[i].ToString() + " ";
                }
                filesSystemMaster.executStringCommand(cmd);
            }

        }

        private void BtnConnect_Click(object sender, EventArgs e)
        {
            if (chLstBxServers.CheckedItems.Count > 0)
            {
                string cmd = "connectS ";
                for (int i = 0; i < chLstBxServers.CheckedItems.Count; i++)
                {
                    cmd += chLstBxServers.CheckedItems[i].ToString() + " ";
                }
                filesSystemMaster.executStringCommand(cmd);
            }

            this.TreeView.Nodes.Clear();
            this.TreeView.Nodes.Add(new TreeNode("root"));
            //this.TreeView.Nodes[0].Nodes.Add(new TreeNode("dir1"));
           // this.TreeView..Nodes.Insert(1, "subdir");
        }

        private void TreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
           // filesSystemMaster.executStringCommand("cd " + e.Node.FullPath);
            if (e.Node.FullPath == "root")
            {
                Command responseCmd = filesSystemMaster.executStringCommand("ls");
                execCommand(responseCmd);
            }
            else
            {
                Command responseCmd = filesSystemMaster.executStringCommand("cd " + e.Node.FullPath.Substring(5));
                execCommand(responseCmd);

                responseCmd = filesSystemMaster.executStringCommand("ls " + e.Node.FullPath.Substring(5));
                execCommand(responseCmd);
            }

             //dis//e.Node.FullPath
        }

        private void TreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Node.FullPath == "root")
            {
                Command responseCmd = filesSystemMaster.executStringCommand("ls");
                execCommand(responseCmd);
            }
            else
            {
                Command responseCmd = filesSystemMaster.executStringCommand("ls " + e.Node.FullPath.Substring(5));
                execCommand(responseCmd);
            }

        }

        private void TreeView_MouseUp(object sender, MouseEventArgs e)
        {
        /*    if (e.Node.FullPath == "root")
            {
                filesSystemMaster.executStringCommand("ls");
            }
            else
            {
                filesSystemMaster.executStringCommand("ls " + e.Node.FullPath);
            }*/

        }
    }
}